package dryven.model.validation;

import dryven.i18n.Translator;
import dryven.model.di.LocalThreadStorage;

public class DefaultValidatorSession implements ValidatorSession {
	private ValidatorService _validatorService;
	private ValidationReporterImpl _reporter;
	private Translator _translator;
	private boolean _hasErrors = false;
	private MapErrorMessageCollection _errorMessages;
	private LocalThreadStorage _storage;
	
	public DefaultValidatorSession(ValidatorService service, Translator tr, LocalThreadStorage storage) {
		super();
		_validatorService = service;
		_translator = tr;
		_reporter = new ValidationReporterImpl();
		_errorMessages = new MapErrorMessageCollection();
		_storage = storage;
	}

	@Override
	public ErrorMessageCollection getErrorMessages() {
		return _errorMessages;
	}

	@Override
	public boolean hasErrors() {
		return _hasErrors;
	}

	@Override
	public Object validate(ValidationFieldDescription desc,
			ValidationFormValueCollection form,
			Class<? extends Validator> validator) throws ValidationException {
		Validator v = _validatorService.instanciateValidator(_storage, validator);
		_reporter.reset();
		v.validate(desc, form, _reporter);
		if(_reporter.hasErrors()) {
			_hasErrors = true;
			_errorMessages.merge(_reporter.getErrors());
			throw new ValidationException();
		} else {
			return _reporter.getConvertedValue();
		}
	}
	
	class ValidationReporterImpl implements ValidationReporter {

		private boolean _hasErrors;
		private Object _convertedValue;
		private MapErrorMessageCollection _errors = new MapErrorMessageCollection();
		
		@Override
		public void reportError(String fieldName, String messageKey,
				Object... params) {
			_hasErrors = true;
			ErrorMessage msg = new StringErrorMessage(_translator.translate(messageKey, params));
			_errors.addMessage(fieldName, msg);
		}

		@Override
		public void reportLiteralError(String fieldName, String errorMessage) {
			_hasErrors = true;
			ErrorMessage msg = new StringErrorMessage(errorMessage);
			_errors.addMessage(fieldName, msg);
		}

		@Override
		public void valueConverted(Object newValue) {
			_convertedValue = newValue;
		}

		@Override
		public Object getConvertedValue() {
			return _convertedValue;
		}
		
		public boolean hasErrors() {
			return _hasErrors;
		}
		
		public void reset() {
			_hasErrors = false;
			_convertedValue = null;
		}
		
		public ErrorMessageCollection getErrors() {
			return _errors;
		}
		
	}

}
